home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / Tools / freeWAIS-sf-1.1 / ui / wais-ui.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-01-10  |  21.0 KB  |  855 lines

  1. /* 
  2.   WIDE AREA INFORMATION SERVER SOFTWARE:
  3.    No guarantees or restrictions.  See the readme file for the full standard
  4.    disclaimer.
  5.  
  6.    This is part of the shell user-interface tools for the WAIS software.
  7.    Do with it as you please.
  8.  
  9.    jonathan@Think.COM
  10. */
  11.  
  12. /* Copyright (c) CNIDR (see ../COPYRIGHT) */
  13.  
  14. /*
  15.  * $Log: wais-ui.c,v $
  16.  * Revision 1.3  1995/01/10  16:50:57  pfeifer
  17.  * Fix from Jonny
  18.  *
  19.  * Revision 1.2  1994/08/05  07:30:21  pfeifer
  20.  * Release beta 04
  21.  *
  22.  * Revision 1.31  93/06/23  20:02:23  warnock
  23.  * Initial revision
  24.  * 
  25.  * Revision 1.3  1993/02/16  15:09:27  freewais
  26.  * Initial revision
  27.  *
  28.  * $Log: wais-ui.c,v $
  29.  * Revision 1.3  1995/01/10  16:50:57  pfeifer
  30.  * Fix from Jonny
  31.  *
  32.  * Revision 1.2  1994/08/05  07:30:21  pfeifer
  33.  * Release beta 04
  34.  *
  35.  * Revision 1.24  92/06/03  17:19:20  jonathan
  36.  * Reset signal handlers on use.  From mycroft@gnu.ai.mit.edu.
  37.  * 
  38.  * Revision 1.23  92/05/19  17:19:50  jonathan
  39.  * Fixed bug where RetrieveWaisDocument failed to remove Seeker markup.
  40.  * 
  41.  * Revision 1.22  92/05/07  14:52:04  jonathan
  42.  * Changed use of setitimer to alarm.  Thanks to
  43.  * steinkel@carlisle-emh2.army.mil.
  44.  * 
  45.  * Revision 1.21  92/04/30  10:59:05  jonathan
  46.  * Replace strdup with s_strdup.
  47.  * 
  48.  * Revision 1.20  92/04/02  14:21:59  jonathan
  49.  * Copy type in all calls to makeDocObjUsing a generate_retrieval_apdu (which
  50.  * calls makeDocObjUsing...).
  51.  * 
  52.  * Revision 1.19  92/04/01  17:19:35  jonathan
  53.  * Fixed reporting of diagnostics when return text is empty.
  54.  * 
  55.  * Revision 1.18  92/03/17  14:33:17  jonathan
  56.  * Renamed to wais-ui, cleaned up for use by X interface as well as shell
  57.  * interfaces.
  58.  * 
  59.  * Revision 1.17  92/03/08  10:42:28  jonathan
  60.  * Added one last loadSource in ViewWaisDocument.
  61.  * 
  62.  * Revision 1.16  92/03/06  14:50:13  jonathan
  63.  * New and Improved source loading!
  64.  * 
  65.  */
  66.  
  67. #ifndef lint
  68. static char *RCSid = "$Header: /usr/local/ls6/src+data/src/freeWAIS-sf/ui/RCS/wais-ui.c,v 1.3 1995/01/10 16:50:57 pfeifer Exp $";
  69. #endif
  70.  
  71. #define _C_QUESTION
  72.  
  73. #include "wais.h"
  74. #include "globals.h"
  75.  
  76. void showDiags(d)
  77. diagnosticRecord **d;
  78. {
  79.   int i;
  80.   /* char msg[256]; unused (up) */
  81.  
  82.   for (i = 0; d[i] != NULL; i++) {
  83.     if (d[i]->ADDINFO != NULL) {
  84.       PrintStatus(STATUS_URGENT, STATUS_HIGH, DIAG_MESSAGE,
  85.           d[i]->DIAG, d[i] ->ADDINFO);
  86.     }
  87.   }
  88. }
  89.       
  90. void printDiags(d)
  91. diagnosticRecord **d;
  92. {
  93.   int i;
  94.  
  95.   for (i = 0; d[i] != NULL; i++)
  96.     if (d[i]->ADDINFO != NULL)
  97.       printf("%s\n", d[i] ->ADDINFO);
  98. }
  99.       
  100. void
  101. write_text_record_completely(fp, record, quote_string_quotes)
  102. FILE *fp;
  103. WAISDocumentText *record;
  104. Boolean quote_string_quotes;
  105. {
  106.   long count;
  107.   /* fprintf(fp," Text\n");
  108.   print_any("     DocumentID:  ", record->DocumentID);
  109.   fprintf(fp,"     VersionNumber:  %d\n", record->VersionNumber);
  110.   */
  111.   for(count = 0; count < record->DocumentText->size; count++){
  112.     int ch = record->DocumentText->bytes[count];
  113.     if(27 == ch){
  114.       /* then we have an escape code */
  115.       /* if the next letter is '(' or ')', then ignore two letters */
  116.       if('(' == record->DocumentText->bytes[count + 1] ||
  117.       ')' == record->DocumentText->bytes[count + 1])
  118.     count += 1;             /* it is a term marker */
  119.       else count += 4;         /* it is a paragraph marker */
  120.     }
  121.     else if (isprint(ch)){
  122.       if(quote_string_quotes && ch == '"')
  123.     putc('\\', fp);
  124.       putc(ch, fp);
  125.     } 
  126.     else if (ch == '\n' || ch == '\r')
  127.       fprintf(fp, "\n");
  128.   }
  129. }
  130.  
  131.  
  132. /* for making searches */
  133.  
  134. DocList
  135. build_response_list(response, source, seed_words_used)
  136. SearchResponseAPDU *response;
  137. SourceID source;
  138. char** seed_words_used;
  139. {
  140.   long i, k;
  141.   WAISSearchResponse  *info;
  142.   DocList last = NULL, doc, result = NULL;
  143.   DocumentID docID;
  144.  
  145.   k = response->NumberOfRecordsReturned;
  146.  
  147.   if ( response->DatabaseDiagnosticRecords != 0 ) {
  148.     info = (WAISSearchResponse*)response->DatabaseDiagnosticRecords;
  149.     if(seed_words_used != NULL) {
  150.       if(*seed_words_used != NULL) s_free(*seed_words_used);
  151.       if(info->SeedWordsUsed != NULL)
  152.     *seed_words_used = s_strdup(info->SeedWordsUsed);
  153.     }
  154.     if ( info->DocHeaders != NULL ) {
  155.       for(i = 0; i < k; i++) {
  156.     if(info->DocHeaders[i] != NULL ) {
  157.       if(result == NULL) {
  158.         doc = result = makeDocList(NULL, NULL);
  159.       }
  160.       else
  161.         doc = makeDocList(NULL, NULL);
  162.  
  163.       docID = fillDocumentID(info->DocHeaders[i], source);
  164.       doc->thisDoc = docID;
  165.  
  166.       if(last != NULL) {
  167.         last->nextDoc = doc;
  168.       }
  169.       last = doc;
  170.     }
  171.       }
  172.     }
  173.   }
  174.   return result;
  175. }
  176.  
  177. /* right now this hacks out the ^Q/S too.  I'll do better later. */
  178.  
  179. void replacecontrolM(buffer, length)
  180. char *buffer;
  181. long *length;
  182. {
  183.   char *here, *there, c;
  184.   long i, newlength;
  185.  
  186.   here = there = buffer;
  187.   for(newlength = 0, i = 0; i < *length; i++) {
  188.     c = *here;
  189.     switch (c) {
  190.     case 0:
  191.       *there = 0;
  192.       *length = newlength;
  193.       return;
  194.     case '\r':
  195.       *there = '\n';
  196.       newlength++;
  197.       here++; there++;
  198.       break;
  199.     case 19:
  200.     case 17:
  201.       here++;
  202.       break;
  203.     default:
  204.       *there = *here;
  205.       newlength++;
  206.       here++; there++;
  207.     }
  208.   }
  209.   *length = newlength;
  210. }
  211.  
  212. /* This is a compy from ../x/qcommands.c (up) */
  213.  
  214. static void
  215. truncate_document_list(dl, n)
  216. DocList dl;
  217. long n;
  218. {
  219.   while(--n > 0)
  220.     if(dl == NULL ||
  221.        (dl = dl->nextDoc) == NULL)
  222.       return;
  223.  
  224.   freeDocList(dl->nextDoc);
  225.   dl->nextDoc = NULL;
  226.   return;
  227. }
  228.  
  229. void SearchWais(q)
  230. Question q;
  231. {
  232.   Source source;
  233.   /* SList asource; unused (up) */
  234.   static long request_buffer_length;
  235.   DocObj **Doc;
  236.   int i;
  237.   char *request_message, *response_message;
  238.   /* char message[255]; unused (up) */
  239.   DocList last;
  240.   diagnosticRecord **diag;
  241.   char *database;
  242.   long numdocs, result;
  243.   WAISSearchResponse *response;
  244.  
  245.   request_message = (char*)q->request_message;
  246.   response_message = (char*)q->response_message;
  247.  
  248.   /* clear the results */
  249.  
  250.   /*
  251.   freeDocList(q->ResultDocuments);
  252.   */
  253.   q->ResultDocuments = NULL;
  254.  
  255.   /* build DocObjs */
  256.  
  257.   Doc = (DocObj**)s_malloc((q->numdocs+1) * sizeof(char*));
  258.   
  259.   q->numsources = listlength((List)q->Sources);
  260.  
  261.   numdocs = q->maxresdocs;
  262.   {
  263.     DocList dl;
  264.     for(i=0, dl = q->RelevantDocuments;
  265.     dl != NULL;
  266.     dl = dl->nextDoc, i++)
  267.       if(dl->thisDoc->doc != NULL) {
  268.     char* tmptype = s_strdup((dl->thisDoc->doc->type) ?
  269.                  dl->thisDoc->doc->type[0] : "TEXT");
  270.  
  271.     if(dl->thisDoc->doc->id != NULL)
  272.       if(dl->thisDoc->start >= 0)
  273.           
  274.         Doc[i] =
  275.           makeDocObjUsingLines(anyFromDocID(dl->thisDoc->doc->id),
  276.                    tmptype, dl->thisDoc->start, dl->thisDoc->end);
  277.       else
  278.         Doc[i] =
  279.           makeDocObjUsingWholeDocument(anyFromDocID(dl->thisDoc->doc->id),
  280.                        tmptype);
  281.  
  282.       }
  283.     Doc[i] = NULL;
  284.   }
  285.  
  286.   /* check to see if the question has a source */
  287.   source = NULL;
  288.  
  289.   if(q->Sources != NULL) {
  290.     SourceList slist;
  291.  
  292.     for(slist = q->Sources;
  293.     slist != NULL;
  294.     slist = slist->nextSource) {
  295.       source = findsource(slist->thisSource->filename, q->sourcepath);
  296.  
  297.       if (source == NULL) {
  298.     PrintStatus(STATUS_URGENT, STATUS_HIGH, NOSOURCE_MESSAGE,
  299.             slist->thisSource->filename);
  300.       }
  301.       else {
  302.     PrintStatus(STATUS_INFO, STATUS_LOW, SEARCH_MESSAGE, source->name);
  303.       
  304.     if(source->initp != TRUE) {
  305.       PrintStatus(STATUS_INFO, STATUS_LOW, INITSOURCE_MESSAGE);
  306.       init_for_source(source, request_message, MAX_MESSAGE_LEN, 
  307.               response_message);
  308.     }
  309.     if(source->database[0] == 0) database = NULL;
  310.     else database = source->database;
  311.  
  312.     if(source->initp != FALSE) {
  313.       result = 0;
  314.       request_buffer_length = source->buffer_length;
  315.       if(NULL ==
  316.          generate_search_apdu(request_message + HEADER_LENGTH, 
  317.                   &request_buffer_length, 
  318.                   q->keywords, database, Doc, numdocs)) {
  319.         PrintStatus(STATUS_URGENT, STATUS_HIGH, BUFFOVER_MESSAGE);
  320.       }
  321.       else if((result =
  322.            interpret_message(request_message, 
  323.                      (source->buffer_length - 
  324.                       request_buffer_length), 
  325.                      response_message,
  326.                      source->buffer_length,
  327.                      source->connection,
  328.                      false /* true verbose */
  329.                      )) == 0) {
  330.         PrintStatus(STATUS_URGENT, STATUS_LOW, NODATA_MESSAGE);
  331.         close_source(source);
  332.       }
  333.       if (result != 0) { /* use the repsonse */
  334.         readSearchResponseAPDU(&q->query_response,
  335.                    response_message + HEADER_LENGTH);
  336.  
  337.       
  338.         if (q->query_response != NULL)
  339.           if ((response = (WAISSearchResponse *)
  340.            q->query_response->DatabaseDiagnosticRecords) != NULL)  {
  341.         if ((diag = response->Diagnostics) != NULL)
  342.           showDiags(diag);
  343.       
  344.         if (q->ResultDocuments != NULL) {
  345.           char* keys_used = NULL;
  346.           last = findLast(q->ResultDocuments);
  347.           last->nextDoc = build_response_list(q->query_response,
  348.                               slist->thisSource,
  349.                               &keys_used);
  350.           if (keys_used != NULL) {
  351.             if (keys_used[0] != 0) {
  352.               if(q->keywords_used == NULL) q->keywords_used = keys_used;
  353.               else {
  354.             if(strcmp(q->keywords_used, keys_used) != 0) {
  355.               q->keywords_used =
  356.                 (char*)s_realloc(q->keywords_used,
  357.                          strlen(q->keywords_used) + strlen(keys_used) +1);
  358.               strcat(q->keywords_used, " ");
  359.               strcat(q->keywords_used, keys_used);
  360.             }
  361.               }
  362.               s_free(keys_used);
  363.             }
  364.           }
  365.         }
  366.         else
  367.           q->ResultDocuments =
  368.             build_response_list(q->query_response,
  369.                     slist->thisSource,
  370.                     &q->keywords_used);
  371.         freeWAISSearchResponse(response);
  372.           }
  373.       }
  374.     }
  375.     else {
  376.       PrintStatus(STATUS_URGENT, STATUS_HIGH, INITFAIL_MESSAGE);
  377.     }
  378.       }
  379.       sort_document_list(q->ResultDocuments);
  380.       truncate_document_list(q->ResultDocuments, q->maxresdocs);
  381.     }
  382.     /* ok, now we've got all the documents, let's sort them */
  383.  
  384.     sort_document_list(q->ResultDocuments);
  385.  
  386.     q->numresdocs =  listlength((List)q->ResultDocuments);
  387.     PrintStatus(STATUS_INFO, STATUS_MEDIUM, FOUND_MESSAGE, q->numresdocs);
  388.   }
  389.   else {
  390.     PrintStatus(STATUS_URGENT, STATUS_HIGH,
  391.         "\nThis Question has no sources to search.  Please add one.");
  392.     q->ResultDocuments = NULL;
  393.     q->numresdocs =  listlength((List)q->ResultDocuments);
  394.   }
  395.   if (Doc != NULL) {
  396.     doList((void**)Doc,freeDocObj);
  397.     s_free(Doc);
  398.   }
  399. }
  400.  
  401. char* GetWaisDocument(q, doc, type, fp, written)
  402. Question q;
  403. DocumentID doc;
  404. char *type;
  405. FILE *fp;
  406. long* written;
  407. {
  408.   static long request_length, chars_per_page;
  409.   static long lines, size, count, chars, numChars;
  410.   long start_byte, end_byte;
  411.   any* docany;
  412.   WAISDocumentText *text;
  413.   diagnosticRecord **diag;
  414.   char *viewtext/* , message[255] unused */;
  415.   char *viewbuffer;
  416.   char *tmptype;
  417.   Source source;
  418.   /* SList asource;unused */
  419.   char *database;
  420.   long result;
  421.   WAISSearchResponse *response;
  422.  
  423.   source = NULL;
  424.  
  425.   if(doc == NULL) return NULL;
  426.  
  427.   if(doc->doc != NULL &&
  428.      doc->doc->sourceID != NULL &&
  429.      doc->doc->sourceID->filename != NULL) {
  430.     source = findsource(doc->doc->sourceID->filename, q->sourcepath);
  431.   }
  432.  
  433.   if (source == NULL) {
  434.     PrintStatus(STATUS_URGENT, STATUS_HIGH, NOSOURCE_MESSAGE,
  435.         doc->doc->sourceID->filename);        
  436.     return NULL;
  437.   }
  438.  
  439.   if(fp != stdout)
  440.     PrintStatus(STATUS_INFO, STATUS_MEDIUM, GETDOC_MESSAGE, 
  441.         doc->doc->headline, source->name);
  442.  
  443.   if(source->database[0] == 0) database = NULL;
  444.   else database = source->database;
  445.  
  446.   size = 0;
  447.  
  448.   lines = doc->doc->numLines;
  449.   if(written != NULL && *written != 0)
  450.     chars = *written;
  451.   else
  452.     chars = doc->doc->numChars;
  453.  
  454.   numChars = chars+1000;    /* for slop? */
  455.  
  456.   docany = anyFromDocID(doc->doc->id);
  457.  
  458.   if(source->initp == FALSE)
  459.     init_for_source(source, q->request_message, MAX_MESSAGE_LEN,
  460.             q->response_message);
  461.  
  462.  
  463.   if(source->initp == FALSE) {
  464.     PrintStatus(STATUS_URGENT, STATUS_HIGH, INITFAIL_MESSAGE);
  465.     *written = 0;
  466.     return(NULL);
  467.   }
  468.  
  469.   chars_per_page = source->buffer_length - HEADER_LENGTH - 1000; /* ? */
  470.  
  471.   if(fp == NULL) {
  472.     viewbuffer = (char*)s_malloc(chars < 0 ? chars_per_page : numChars);
  473.  
  474.     if(viewbuffer == NULL) {
  475.       PrintStatus(STATUS_URGENT, STATUS_HIGH, BADALLOC_MESSAGE);
  476.       return NULL;
  477.     }
  478.     viewtext = viewbuffer;
  479.   }
  480.  
  481.   tmptype = s_strdup((type ? type : "TEXT"));
  482.  
  483.   if (chars == 0)
  484.     PrintStatus(STATUS_INFO, STATUS_HIGH,
  485.         "\nEmpty document!");
  486.   else if (source->initp != FALSE) {
  487.     for(count = 0; 
  488.     (chars < 0) || (count * chars_per_page < chars);
  489.     count++) {
  490.       /* show as we go... */
  491.       request_length = source->buffer_length;
  492.  
  493.       if (chars < 0) {
  494.     numChars = (count+1) * chars_per_page;
  495.     if(fp == NULL) {
  496.       viewbuffer = s_realloc(viewbuffer, numChars);
  497.     }
  498.       }
  499.  
  500.       start_byte = count * chars_per_page;
  501.       end_byte = (chars < 0 ? 
  502.           (count + 1) * chars_per_page :
  503.           MINIMUM((count + 1) * chars_per_page, chars));
  504.       if(NULL ==
  505.      generate_retrieval_apdu(q->request_message + HEADER_LENGTH,
  506.                  &request_length, docany, CT_byte,
  507.                  start_byte, end_byte,
  508.                  tmptype, database)) {
  509.     PrintStatus(STATUS_URGENT, STATUS_HIGH, BUFFOVER_MESSAGE);
  510.     return NULL;
  511.       }
  512.          
  513.       if((result =
  514.       interpret_message(q->request_message, 
  515.                 source->buffer_length - request_length, 
  516.                 q->response_message,
  517.                 source->buffer_length,
  518.                 source->connection,
  519.                 false /* true verbose */    
  520.                 )) == 0) {
  521.     PrintStatus(STATUS_URGENT, STATUS_HIGH, NODATA_MESSAGE);
  522.     close_source(source);
  523.     return NULL;
  524.       }
  525.       if (result != 0) 
  526.     readSearchResponseAPDU(&q->retrieval_response, 
  527.                    q->response_message + HEADER_LENGTH);
  528.  
  529.       if (q->retrieval_response != NULL)  {
  530.     if ((response = (WAISSearchResponse *)
  531.          q->retrieval_response->DatabaseDiagnosticRecords) != NULL) {
  532.       diag = response->Diagnostics;
  533.  
  534.       if(NULL == response->Text) {
  535.         if (diag != NULL)
  536.           showDiags(diag);
  537.     
  538.         PrintStatus(STATUS_INFO, STATUS_MEDIUM, DONE_MESSAGE);
  539.         if(written != NULL) *written = size;
  540.         return(viewbuffer);
  541.       }
  542.       else {
  543.         text = response->Text[0];
  544.         if((type == NULL) || (strcmp(type, "TEXT") == 0)) {
  545.           long length = text->DocumentText->size;;
  546.         
  547.           delete_seeker_codes(text->DocumentText->bytes, &length);
  548.           text->DocumentText->size = length;
  549.           replacecontrolM(text->DocumentText->bytes, &length);
  550.           text->DocumentText->size = length;
  551.         }
  552.  
  553.         if(text->DocumentText->size > (end_byte - start_byte))
  554.           /* something wrong! */
  555.           text->DocumentText->size = (end_byte - start_byte);
  556.  
  557.         viewtext = viewbuffer+size;
  558.         size+=text->DocumentText->size;
  559.         if (size <= numChars) {
  560.           if(fp == NULL) {
  561.         memcpy(viewtext, text->DocumentText->bytes, text->DocumentText->size);
  562.           }
  563.           else {
  564.         dumptext(fp, text->DocumentText->bytes, text->DocumentText->size);
  565.           }
  566.  
  567.           if(fp != stdout)
  568.         PrintStatus(STATUS_CONT, STATUS_LOW, RECEIVE_MESSAGE,
  569.                 size, source->name);
  570.  
  571.           if(diag &&
  572.          diag[0] &&
  573.          diag[0]->ADDINFO != NULL &&
  574.          !strcmp(diag[0]->DIAG, D_PresentRequestOutOfRange))
  575.         break;
  576.           if((type != NULL) &&
  577.          (strcmp(type, "TEXT") != 0) &&
  578.          (text->DocumentText->size != chars_per_page))
  579.         break;
  580.         }
  581.         else {
  582.           PrintStatus(STATUS_URGENT, STATUS_HIGH, BUFFOVER_MESSAGE);
  583.           break;
  584.         }
  585.       }
  586.  
  587.       if (diag != NULL)
  588.         showDiags(diag);
  589.  
  590.       freeWAISSearchResponse(response);
  591.     }
  592.       }
  593.     }
  594.   }
  595.   if (written != NULL) *written = size;
  596.   return(viewbuffer);
  597. }
  598.  
  599. void RetrieveWaisDocument(start_output, end_output, q, doc)
  600. void (*start_output)();
  601. void (*end_output)();
  602. Question q;
  603. DocumentID doc;
  604. {
  605.   FILE *fp;
  606.   int output_started;
  607.   int screen_output;
  608.   long written = 0;
  609.   char *result;
  610.  
  611.   output_started = FALSE;
  612.   screen_output = FALSE;
  613.  
  614.   if (output_started==FALSE) {
  615.     if (start_output != NULL) {
  616.       start_output(&fp);
  617.       screen_output = FALSE;
  618.       if (&fp==NULL) {
  619.     PrintStatus(STATUS_URGENT, STATUS_HIGH, "Unable to open output.");
  620.     return;
  621.       }
  622.     } else {
  623.       screen_output = TRUE;
  624.       fp = NULL;
  625.     }
  626.       output_started=TRUE;
  627.   }
  628.  
  629.   result = GetWaisDocument(q, doc, 
  630.                (doc->doc->type ?
  631.                 (doc->doc->type[0] ?
  632.                  doc->doc->type[0]:"TEXT"):"TEXT"),
  633.                fp, &written);
  634.  
  635.   if (screen_output == TRUE)
  636.     DumpTextToScreen(result, written);
  637.  
  638.   if ((output_started==TRUE) && (screen_output == FALSE))
  639.     end_output(&fp);
  640. }
  641.  
  642. void dumptext(fp, buffer, size)
  643. FILE *fp;
  644. char *buffer;
  645. long size;
  646. {
  647.   long i;
  648.  
  649.   for (i = 0; i < size; i++)
  650.     fputc(*buffer++,fp);
  651.   fflush(fp);
  652. }
  653.  
  654. void test_connection(q)
  655. Question q;
  656. {
  657.   Source source;
  658.   SList asource;
  659.   static long request_buffer_length;
  660.   char *request_message, *response_message;
  661.   /* char message[255]; unused (up)*/
  662.   diagnosticRecord **diag;
  663.   char *database;
  664.  
  665.   request_message = (char*)q->request_message;
  666.   response_message = (char*)q->response_message;
  667.  
  668.   /* check to see if the question has a source */
  669.   source = NULL;
  670.  
  671.   if(q->Sources != NULL) {
  672.     SourceList slist;
  673.  
  674.     for(slist = q->Sources;
  675.     slist != NULL;
  676.     slist = slist->nextSource) {
  677.       for(asource = Sources;
  678.       asource != NULL;
  679.       asource = asource->nextSource) {
  680.     if (asource->thisSource != NULL &&
  681.         asource->thisSource->name != NULL &&
  682.         !strcmp(slist->thisSource->filename,
  683.             asource->thisSource->name)) {
  684.       source = asource->thisSource;
  685.       break;
  686.     }
  687.       }
  688.  
  689.       if (source == NULL) {
  690.     PrintStatus(STATUS_URGENT, STATUS_HIGH, NOSOURCE_MESSAGE, 
  691.             slist->thisSource->filename);
  692.       }
  693.       else {
  694.     printf("Source %s ", slist->thisSource->filename);
  695.     if(source->maintainer) 
  696.       printf("by %s ", source->maintainer);
  697.     if(source->server[0] != 0)
  698.       printf("at %s ", source->server);
  699.  
  700.     if(source->initp == FALSE) {
  701.       freopen("/dev/null", "w", stderr);
  702.       init_for_source(source, q->request_message, MAX_MESSAGE_LEN,
  703.               q->response_message);
  704.       request_buffer_length = source->buffer_length;
  705.  
  706.       if(source->initp == FALSE) {
  707.         printf("not responding.\n");
  708.       }
  709.       else {        /* now lets test the database */
  710.         if(source->database[0] == 0) database = NULL;
  711.         else database = source->database;
  712.  
  713.         if(NULL ==
  714.            generate_search_apdu(request_message + HEADER_LENGTH, 
  715.                     &request_buffer_length, 
  716.                     "?", database, NULL, 1)) {
  717.           PrintStatus(STATUS_URGENT, STATUS_HIGH, BUFFOVER_MESSAGE);
  718.         }
  719.         else {
  720.           long r = 0;
  721.           if(0 == 
  722.          (r = interpret_message(request_message, 
  723.                     (source->buffer_length - 
  724.                      request_buffer_length), 
  725.                     response_message,
  726.                     source->buffer_length,
  727.                     source->connection,
  728.                     false /* true verbose */
  729.                     ))) {
  730.         PrintStatus(STATUS_URGENT, STATUS_HIGH, NODATA_MESSAGE);
  731.           }
  732.           if(r != 0) {
  733.         readSearchResponseAPDU(&q->query_response,
  734.                        response_message + HEADER_LENGTH);
  735.  
  736.       
  737.         if (q->query_response != NULL)
  738.           if ((WAISSearchResponse *)q->query_response->DatabaseDiagnosticRecords != NULL) 
  739.             if ((diag =
  740.              ((WAISSearchResponse *)q->query_response->DatabaseDiagnosticRecords)->Diagnostics) != NULL) {
  741.               printf("not responding:\n");
  742.               printDiags(diag);
  743.             }
  744.             else 
  745.               printf("responding.\n");
  746.           }
  747.         }
  748.       }
  749.     }
  750.       }
  751.     }
  752.   }
  753.   else {
  754.     printf("\nError: No sources to search.  Please add one.\n");
  755.   }
  756. }
  757.  
  758. void close_source(source)
  759. Source source;
  760. {
  761.   SList t;
  762.  
  763.   if (source->connection != NULL) {
  764.     fclose(source->connection);
  765.   }
  766.   for(t = Sources; t != NULL; t = t->nextSource) {
  767.     if (strcmp(t->thisSource->server, source->server) == 0 &&
  768.     strcmp(t->thisSource->service, source->service) == 0) {
  769.       t->thisSource->initp = FALSE;
  770.       t->thisSource->connection = NULL;
  771.     }
  772.   }
  773. }
  774.  
  775. DocumentID
  776.  getNextorPrevDoc(q, source, doc, nextp)
  777. Question q;
  778. Source source;
  779. DocumentID doc;
  780. Boolean nextp;
  781. {
  782.   static long request_length;
  783.   static long size /*, lines, count, numChars unused (up) */;
  784.   any* docany;
  785.   /* char message[255]; unused */
  786.   /* int i; unused (up) */
  787.   diagnosticRecord **diag;
  788.   char *database, *type;
  789.   /* DocumentID result; unused (up) */
  790.   /* DocID *newdoc; unused (up) */
  791.   DocObj *Doc[2];
  792.   WAISSearchResponse  *info;
  793.   /* char *text, document_id[MAX_FILE_NAME_LEN] unused */;
  794.   /* char *loc1, *loc2, *loc3, newtype[100], headline[MAX_FILE_NAME_LEN] unused */;
  795.   /* long newsize; unused */
  796.  
  797.   if(source->database[0] == 0) database = NULL;
  798.   else database = source->database;
  799.  
  800.   docany = anyFromDocID(doc->doc->id);
  801.  
  802.   size = 0;
  803.  
  804.   if(nextp == TRUE)
  805.     type = "WAIS_NEXT";
  806.   else
  807.     type = "WAIS_PREV";
  808.  
  809.   if(source->initp == FALSE)
  810.     init_for_source(source,q->request_message,MAX_MESSAGE_LEN,
  811.             q->response_message);
  812.  
  813.   request_length = source->buffer_length;
  814.   
  815.   Doc[0] = makeDocObjUsingWholeDocument(docany, s_strdup(type));
  816.   Doc[1] = NULL;
  817.   if(0 ==
  818.      generate_search_apdu(q->request_message + HEADER_LENGTH, 
  819.               &request_length, 
  820.               "foo", database, Doc, 1)) {
  821.     PrintStatus(STATUS_URGENT, STATUS_HIGH, BUFFOVER_MESSAGE);
  822.     return NULL;
  823.   }
  824.          
  825.   if(0 ==
  826.      interpret_message(q->request_message, 
  827.                (source->buffer_length - request_length), 
  828.                q->response_message,
  829.                source->buffer_length,
  830.                source->connection,
  831.                false    /* true verbose */    
  832.                )) {
  833.     PrintStatus(STATUS_URGENT, STATUS_HIGH, NODATA_MESSAGE);
  834.     source->initp = FALSE;
  835.     return NULL;
  836.   }
  837.  
  838.   readSearchResponseAPDU(&q->retrieval_response, 
  839.              q->response_message + HEADER_LENGTH);
  840.  
  841.   if (q->retrieval_response != NULL)
  842.     if ((WAISSearchResponse *)q->retrieval_response->DatabaseDiagnosticRecords != NULL) 
  843.       if ((diag =
  844.        ((WAISSearchResponse *)q->retrieval_response->DatabaseDiagnosticRecords)->Diagnostics) != NULL)
  845.     showDiags(diag);
  846.  
  847.   info = (WAISSearchResponse *)q->retrieval_response->DatabaseDiagnosticRecords;
  848.  
  849.   if (info != NULL &&
  850.       info->DocHeaders != NULL) {
  851.     return(fillDocumentID(info->DocHeaders[0], doc->doc->sourceID));
  852.   }
  853.   else return NULL;
  854. }
  855.